'''
Created on Oct 11, 2012

@author: raygomez
'''

from ProtocolConstants import AVP_MESSAGES
class MessageHeader:
    
    COMMAND_REQUEST_FLAG    = 0x80
    COMMAND_PROXIABLE_FLAG  = 0x40
    COMMAND_ERROR_FLAG      = 0X20
    COMMAND_RETRANSMIT_FLAG = 0X10
    
    def __init__(self, that=None):
        
        if not that:
            self.version = 1
            self.commandFlags = 0
            self.commandCode = 0
            self.applicationID = 0
            self.hopByHopIdentifier = 0
            self.endToEndIdentifier = 0
            self.length = 0            
        else:
            self.version = that.version
            self.commandFlags = that.commandFlags
            self.commandCode = that.commandCode
            self.applicationID = that.applicationID
            self.hopByHopIdentifier = that.hopByHopIdentifier
            self.endToEndIdentifier = that.endToEndIdentifier
            self.length = that.length

    def isRequest(self):
        return (self.commandFlags & MessageHeader.COMMAND_REQUEST_FLAG) != 0

    def isProxiable(self):
        return (self.commandFlags & MessageHeader.COMMAND_PROXIABLE_FLAG) != 0

    def isError(self):
        return (self.commandFlags & MessageHeader.COMMAND_ERROR_FLAG) != 0

    def isRetransmit(self):
        return (self.commandFlags & MessageHeader.COMMAND_RETRANSMIT_FLAG) != 0
    
    def setRequest(self, f):
        if f:
            self.commandFlags = (self.commandFlags | MessageHeader.COMMAND_REQUEST_FLAG)
        else:
            self.commandFlags = (self.commandFlags & ~MessageHeader.COMMAND_REQUEST_FLAG)
            
    def setProxiable(self, f):
        if f:
            self.commandFlags = (self.commandFlags | MessageHeader.COMMAND_PROXIABLE_FLAG)
        else:
            self.commandFlags = (self.commandFlags & ~MessageHeader.COMMAND_PROXIABLE_FLAG)

    def setError(self, f):
        if f:
            self.commandFlags = (self.commandFlags | MessageHeader.COMMAND_ERROR_FLAG)
        else:
            self.commandFlags = (self.commandFlags & ~MessageHeader.COMMAND_ERROR_FLAG)

    def setRetransmit(self, f):
        if f:
            self.commandFlags = (self.commandFlags | MessageHeader.COMMAND_RETRANSMIT_FLAG)
        else:
            self.commandFlags = (self.commandFlags & ~MessageHeader.COMMAND_RETRANSMIT_FLAG)

    def encodeSize(self):
        return 5 * 4
    
    def encode(self, packer, messageLength):
        self.length = messageLength
        packer.pack_uint(self.version << 24 | messageLength )
        packer.pack_uint(self.commandFlags << 24 | self.commandCode)
        packer.pack_uint(self.applicationID)
        packer.pack_uint(self.hopByHopIdentifier)
        packer.pack_uint(self.endToEndIdentifier)
        
    def decode(self, unpacker):
        versionLength = unpacker.unpack_uint()  
        self.version = versionLength >> 24
        self.length = versionLength & 0xFFFFFF
        fCodes = unpacker.unpack_uint()
        self.commandFlags = fCodes >> 24
        self.commandCode = fCodes & 0xFFFFFF
        self.applicationID = unpacker.unpack_uint()
        self.hopByHopIdentifier = unpacker.unpack_uint()
        self.endToEndIdentifier = unpacker.unpack_uint()

    def str_prefix__(self):
        s = ""
        if self.isRequest():
            s += "r"
        if self.isProxiable():
            s += "p"
        if self.isError():
            s += "e"
        if self.isRetransmit():
            s += "t"
        return s
        
    def __str__(self):
        strVersion = 'Version={0}\n'.format(self.version)
        strLength = 'length={0} bytes\n'.format(self.length)
        strFlags = 'flags={0}\n'.format(self.str_prefix__())
        if self.commandCode in AVP_MESSAGES:
            strCode = 'Command Code= {0}({1})\n'.format(AVP_MESSAGES[self.commandCode],self.commandCode)
        else:
            strCode = 'Command Code= {0}\n'.format(self.commandCode)
        strAppId = 'App-ID={0}\n'.format(self.applicationID)
        strHopId = 'Hop-by-Hop ID={0}\n'.format(self.hopByHopIdentifier)
        strEndId = 'End-to-end ID={0}\n'.format(self.endToEndIdentifier) 
        return strVersion + strLength + strFlags + strCode + strAppId + strHopId + strEndId
                
    def prepareResponse(self, request):
        self.version = request.version
        self.commandFlags = request.commandFlags & MessageHeader.COMMAND_PROXIABLE_FLAG
        self.commandCode= request.commandCode
        self.applicationID = request.applicationID
        self.hopByHopIdentifier = request.hopByHopIdentifier
        self.endToEndIdentifier = request.endToEndIdentifier